package com.unc.allergyex.helpers;

import com.google.gson.Gson;
import com.unc.allergyex.objects.db.Category;
import com.unc.allergyex.objects.db.Component;
import com.unc.allergyex.objects.db.Dish;
import com.unc.allergyex.objects.db.Restaurant;

/**This class exists solely to take the menu string from the server and deserialize it into the ObjManager.
 * This class is called by the MenuQuerytask after a successful server lookup.  
 * The menu string should have the following format when it comes down from the server:
 * { 
 *  "restaurant": object,
 *  "categories": array of category objects,
 *  "dishes": array of item objects,
 *  "components": array of component objects
 * }			
 * GSON is used to deserialize the menu.
 * @author Stephanie
 * @see com.unc.allergyex.helpers.ObjManager
 */
public class Deserializer {

	/**This is the method that deserializes the JSON menu into the ObjManager using GSON.
	 * It uses calls to helper methods to extract substrings from the overall json string.   
	 * @param menu
	 * @see com.google.gson.Gson
	 */
	public static void deserializeMenu(String menu){
		Gson gson = new Gson();
		
		//deserialize restaurant
		String rjson = extractRestaurant(menu);
		Restaurant restaurant = gson.fromJson(rjson, Restaurant.class);
		ObjManager.setRestaurant(restaurant);
		
		//deserialize categories
		String catjson = extractCategories(menu);
		Category[] cs = gson.fromJson(catjson, Category[].class);
		for (int i = 0; i < cs.length; i++){
			ObjManager.putCategory(cs[i]);
		}
		
		//deserialize components
		String compjson = extractComponents(menu);
		Component[] comps = gson.fromJson(compjson, Component[].class);
		for (int i = 0; i < comps.length; i++){
			ObjManager.putComponent(comps[i]);
		}
		
		//deserialize dishes
		String djson = extractDishes(menu);
		Dish[] dishes = gson.fromJson(djson, Dish[].class);
		for (int i = 0; i < dishes.length; i++){
			ObjManager.putDish(dishes[i]);
		}
	}
	
	/**This is a helper method for extracting the substring that corresponds to the restaurant in the menu.
	 * @param menu the string to extract the restaurant substring from
	 * @return the restaurant substring
	 */
	private static String extractRestaurant(String menu){
		final String startTag = "\"restaurant\":{";
		final char endTag = '}';
		return extractSubstring(menu, startTag, endTag);
	}
	
	/**This is a helper method for extracting the substring that corresponds to the categories in the menu.
	 * @param menu the string to extract the categories substring from
	 * @return the categories substring
	 */
	private static String extractCategories(String menu){
		final String startTag = "\"categories\":[";
		final char endTag = ']';
		return extractSubstring(menu, startTag, endTag);
	}
	
	/**This is a helper method for extracting the substring that corresponds to the dishes in the menu.
	 * @param menu the string to extract the dishes substring from
	 * @return the dishes substring
	 */
	private static String extractDishes(String menu){
		final String startTag = "\"dishes\":[";
		final char endTag = ']';
		return extractSubstring(menu, startTag, endTag);
	}
	
	/**This is a helper method for extracting the substring that corresponds to the components in the menu.
	 * @param menu the string to extract the components substring from
	 * @return the components substring
	 */
	private static String extractComponents(String menu){
		final String startTag = "\"components\":[";
		final char endTag = ']';
		return extractSubstring(menu, startTag, endTag);
	}

	/**This is a helper method that extracts a substring from the menu string given a startTag and an endTag.
	 * This method doesn't stop the substring at the first place that the endtag is seen after the startTag.
	 * Instead, it assumes that the end tag is a ] or a }, and ensures that the substring has matching brackets.
	 * @param menu the string to extract the substring from
	 * @param startTag the tag that begins the substring
	 * @param endTag the tag that ends the substring
	 * @return the substring that starts with startTag and ends with the closing endTag
	 */
	private static String extractSubstring(String menu, String startTag, char endTag) {
		int start = menu.indexOf(startTag)+startTag.length()-1;
		int end = start;
		
		char left = '{';
		char right = '}';
		if (endTag == ']'){
			left = '[';
			right = ']';
		}
		
		int rcount = 0;
		int lcount = 0;
		
		//loop through the characters until we have seen matching brackets of the type that match endTag
		while (rcount <= lcount){
			end++;
			char curr = menu.charAt(end);
			if (curr == left){
				lcount ++;
			}
			if (curr == right){
				rcount ++;
			}
		}
		
		String out = menu.substring(start, end+1);
		return out;
	}
	
}
